// @ts-nocheck
// eslint-disable-next-line no-extra-boolean-cast
import * as ElementPlus from "element-plus";

// import { ElCol, ElForm, ElFormItem, ElInput, ElRow, ElRadio, ElRadioGroup } from "element-plus"
// import { ElButton } from "element-plus/dist/index.full.mjs"
import {
  h,
  render,
  getCurrentInstance,
  markRaw,
  defineComponent,
  Fragment,
  nextTick,
  inject,
  watch,
} from "vue";
import { NextTick } from "../utils/common";

const ruleConf = {
  required: (item) => {
    if (item.strict) {
      return {
        validator: (rule, value, callback) => {
          if (!value || value === "")
            callback(new Error(`${item.ruleLabel}不能为空`));
          else callback();
        },
        trigger: item.trigger || "change",
      };
    }
    return {
      required: true,
      message: `${item.ruleLabel}不能为空`,
      trigger: item.trigger || "change",
    };
  },
  number: (item) => {
    return {
      validator: (rule, value, callback) => {
        if (!item.strict) {
          value = Number(value);
        }
        if (!(typeof value === "number" && Number.isFinite(value)))
          callback(new Error(`${item.ruleLabel}必须为数字`));
        if (value < (item.min ?? item.minNumber)) {
          callback(
            new Error(`${item.ruleLabel}不能小于${item.min ?? item.minNumber}`)
          );
        }
        if (value > (item.max ?? item.maxNumber)) {
          callback(
            new Error(`${item.ruleLabel}不能大于${item.max ?? item.maxNumber}`)
          );
        } else callback();
      },
      trigger: "change",
    };
  },
  custom: (item) => {
    return {
      validator: item.validator,
      message: item.message,
      trigger: item.trigger || "blur",
    };
  },
  minNumber: (item) => {
    return {
      validator: (rule, value, callback) => {
        if (!(typeof value === "number" && Number.isFinite(value)))
          callback(new Error(`${item.ruleLabel}必须为数字`));
        if (value < item.minNumber) {
          callback(new Error(`${item.ruleLabel}不能小于${item.minNumber}`));
        } else callback();
      },
      trigger: "change",
    };
  },
};
const debounce = function (fun, delay = 300) {
  let timer;
  return function () {
    let ctx = this;
    let args = arguments;
    let arr = Array.from(arguments);
    if (timer) {
      clearTimeout(timer);
    }
    if (arr.indexOf("immediate") > -1) {
      fun.apply(ctx, args);
      return;
    }
    timer = setTimeout(() => {
      timer = null;
      try {
        fun.apply(ctx, args);
      } catch (error) {
        console.log(error); //?
      }
    }, delay);
  };
};
const deepClone = (obj) => {
  if (obj === null) return null; // 如果是 null 直接返回 null
  if (typeof obj !== "object") return obj; // 如果 obj 没有子属性直接返回 obj

  let clone = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      clone[key] = deepClone(obj[key]); // 递归调用 deepClone 进行深度拷贝
    }
  }
  return clone;
};
const getTargetDom = (e, flg, loop = 0) => {
  if (flg(e)) {
    return e;
  } else {
    loop += 1;
    if (loop > 8) return null;
    if (!e?.parentNode) {
      return null;
    }
    return getTargetDom(e.parentNode, flg, loop);
  }
};
export default defineComponent({
  props: [
    "formConf",
    // "_parent",
    "clickEvent",
    "visible",
    "dragEvent",
    "evalFunction",
    "changeFunc",
    "useIf",
    "isBind", //!v-model
    "isCom",//是否直接渲染组件
    // "slotName"
  ],
  data() {
    let formName = "formCom_" + Math.ceil(Math.random() * 10 ** 6);
    //if (ctx?.formConf?.name) formName = ctx.formConf.name;

    return {
      // formData: null,
      form: { name: "test" },
      formName,
      customCom: {},
      show: false,
      mergeProp: ["class", "style"],
      unDragList: ["ElOption", "ElRadio"],
      currentCom: null,
      formProp_conf: {},
      rules: {},
      lastRuleConf: "unset",
    };
  },
  watch: {},
  created() {
    let ctx = this;

    // ctx.getForm = inject('formData')
    // ctx.form = ctx.getForm.formConf.props.model ?? {}
    ctx.form = ctx.formConf?.props?.model; //markRaw(ctx.formConf?.props?.model ?? {});
    //  if (ctx.formConf?.props?.model) ctx.formData = ctx.formConf.props.model;
    ctx.evalFunc = ctx.evalFunction ?? inject("evalFunc");
    if (!ctx.evalFunc)
      ctx.evalFunc = (str) => {
        console.log("未创建evalFunc!", str);
      };
    ctx.init(ctx);
  },
  methods: {
    getRules(rules = {}) {
      let ctx = this;
      let newRules = deepClone(rules);
      Object.assign(newRules, ctx.formProp_conf);
      let ruleObj = {};
      Object.keys(newRules).forEach((k) => {
        let field = k;
        let fieldRulesArr = [];
        Object.keys(newRules[k]).forEach((rk) => {
          if (typeof ruleConf[rk] == "function") {
            let item = newRules[k][rk];
            if (!item) return;
            ///执行eval 动态绑定
            Object.keys(item).forEach((kk) => {
              if (kk.startsWith("_")) {
                ////bind变量
                let name = /(?<=_).*/.exec(kk)[0];
                let val;
                if (typeof item[k] == "function") val = item[kk];
                else
                  val =
                    ctx.getValInParent(item[kk]) ??
                    ctx.form[item[kk]] ??
                    undefined;
                if (val === undefined) return;
                item[name] = val;
              }
            });
            let conf = ctx.formProp_conf[k] ?? {};
            if (!item?.ruleLabel) {
              item.ruleLabel =
                newRules[k].ruleLabel ??
                (conf._label && ctx.getValInParent(conf._label)) ??
                conf.label ??
                conf.contentText ??
                "";
            }

            fieldRulesArr.push(ruleConf[rk](newRules[k][rk]));
          }
        });
        ruleObj[field] = fieldRulesArr;
      });
      return ruleObj;
    },
    updateRule: debounce(function (refresh = false) {
      let ctx = this;

      if (!refresh) {
        try {
          if (
            JSON.stringify(ctx.lastRuleConf) ==
            JSON.stringify(ctx.formProp_conf)
          ) {
            return;
          }
        } catch (error) { }
      }
      ctx.lastRuleConf = markRaw(deepClone(ctx.formProp_conf));
      ctx.rules = ctx.getRules(ctx.formConf?.rulesConf);

      ctx.$nextTick(async () => {
        if (ctx.$refs[ctx.formName]) {
          // ctx.$refs[ctx.formName].resetFields();
          ctx.$refs[ctx.formName].clearValidate();
          ctx.$refs[ctx.formName].validate();
          //? change
        }
      });

      // ;(async () => {
      //   await nextTick()
      //   if (childRule.value.length) {
      //     for (let e of childForm.value) {
      //       await e.validate((valid) => {
      //         return valid
      //       })
      //     }
      //   }
      // })()
    }),
    // changeFormData(prop: any, val: any) {
    //   console.log("changeFormData", prop, val)
    //   this.formConf.props.model[prop] = val
    //   //this.$emit('changeFormData', {prop, val})
    // },
    toCamelCase(str) {
      // 将字符串按照 - 或 _ 进行分割
      const words = str.split(/[-_]/);
      // 将第一个单词保持不变，其余单词首字母大写后拼接
      const result = words.reduce((acc, curr, index) => {
        if (index === 0 && curr !== "el") {
          // 不对第一个单词进行修改
          return curr + acc;
        }
        // 将首字母大写后拼接
        return acc + curr.charAt(0).toUpperCase() + curr.slice(1);
      }, "");
      return result;
    },
    getValInParent(str, varys: Object = {}, ...args) {
      let ctx = this;
      let res = null;
      // let v2 = !!ctx.$parent?.form || !!ctx?._parent?.form
      // if (!v2 && typeof ctx.evalFunc === "function") {
      res = ctx.evalFunc(str, varys, args);
      return res;
      // }

      // res = function () {
      //   return eval(str)
      // }.bind(ctx.$parent)()
      // return res
    },
    init(_ctx) {
      let customCom = window._customComponents ?? {};
      if (!window._customComponents) {
        for (const [key, com] of Object.entries(ElementPlus)) {
          customCom[key] = com;
        }
      }

      this.customCom = markRaw(customCom);
      // if (ctx.formConf.rules) {
      // }
    },
    bindEvents(conf: any) {
      let ctx = this;

      // let attr = conf.formItemProps?.formProp || conf.formProp || conf.formItemProps?.prop || conf.prop
      // if (!attr || !ctx.formConf.props?.model || !ctx.formConf.props?.model[attr]) return conf //常量

      if (Array.isArray(conf)) {
        return conf.map((e) => e && ctx.bindEvents(e));
      }
      let getParaRegex = /\((.*?)\)/;

      Object.keys(conf).forEach((k) => {
        let oriFunc = conf[k];
        //增加事件方法变量
        if (k.startsWith("_on") && oriFunc) {
          oriFunc = ctx.getValInParent(oriFunc, conf.varys);
          // if (ctx.clickEvent) {
          //   conf[k] = (e) => {
          //     let str = typeof oriFunc == 'function' ? oriFunc.toString() : oriFunc
          //     if (k.includes('lick')) {
          //       ctx.$emit(ctx.clickEvent, conf, e)
          //     }
          //     e.stopPropagation();
          //   }
          //   return
          // }
          if (!conf?.varys || JSON.stringify(conf.varys) === "{}") return;
          if (typeof oriFunc == "function" && oriFunc.length) {
            let funcStr = oriFunc?.toString() ?? "";
            let params = getParaRegex.exec(funcStr)[1]?.split(",") ?? [];
            let paraArr = new Array(params.length).fill(undefined);
            conf[k] = function (...args: any) {
              let argIndex = 0;
              params.forEach((e, i) => {
                e = e.trim();
                if (e === "varys" || e === "varys2") {
                  //////?
                  paraArr[i] = conf.varys;
                  return;
                }

                Object.keys(conf.varys).forEach((k) => {
                  if (k === e) {
                    paraArr[i] = conf.varys[k];
                  }
                });
                if (paraArr[i] !== undefined) return;

                paraArr[i] = args[argIndex];
                argIndex += 1;
              });
              oriFunc(...paraArr);
            }.bind(ctx);
          }
        }
        if (k.startsWith("on") && oriFunc) {
          if (typeof oriFunc === "string") {
            let strs = getParaRegex.exec(oriFunc)[1] ?? "";
            let params = strs === "" ? strs?.split(",") : [];
            let varyPara =
              params.filter((e) => {
                if (e.replaceAll(" ") === "") return false;
                let flg = /["'`]/.test(e);
                return !flg;
              }) ?? [];
            let varystr = strs;
            varyPara.forEach((e, i) => {
              varystr = varystr.replaceAll(e, `{` + i + `}`);
            });
            oriFunc = oriFunc.replace(strs, varystr);
            oriFunc = eval(
              "(" +
              varyPara.join(",") +
              ")" +
              "=> {ctx.getValInParent(`" +
              oriFunc +
              "`, conf?.varys," +
              varyPara +
              ")}"
            );
            // if (k.includes('lick')) {

            //   oriFunc(2)
            // }
          }
          if (!conf?.varys || JSON.stringify(conf.varys) === "{}") return;
          if (typeof oriFunc == "function" && oriFunc.length) {
            let funcStr = oriFunc?.toString() ?? "";
            let params = getParaRegex.exec(funcStr)[1]?.split(",") ?? [];
            let paraArr = new Array(params.length).fill(undefined);
            conf[k] = function (...args: any) {
              let argIndex = 0;
              params.forEach((e, i) => {
                e = e.trim();
                if (e === "varys" || e === "varys2") {
                  //////?
                  paraArr[i] = conf.varys;
                  return;
                }

                Object.keys(conf.varys).forEach((k) => {
                  if (k === e) {
                    paraArr[i] = conf.varys[k];
                  }
                });
                if (paraArr[i] !== undefined) return;

                paraArr[i] = args[argIndex];
                argIndex += 1;
              });
              oriFunc(...paraArr);
            }.bind(ctx);
          }
          // let v2 = !!ctx.$parent?.form || !!ctx?._parent?.form
        }
      });

      return conf;
    },
    getStr(obj: Object) {
      let newObj = {};
      Object.keys(obj).forEach((k) => {
        if (Object.prototype.toString.call(obj[k]) === "[object Object]") {
          newObj[k] = JSON.stringify(obj[k]);
        } else newObj[k] = obj[k];
      });
      return newObj;
    },
    getFlatJson(obj: Object, evalKeys = true, newObj = {}) {
      let ctx = this;

      Object.keys(obj).forEach((k) => {
        //?change 新增varys变量处理
        if (
          k === "varys" &&
          Object.prototype.toString.call(obj[k]) === "[object Object]"
        ) {
          let newVarys = {};
          Object.keys(obj[k]).forEach((prop) => {
            if (prop.startsWith("_")) {
              let name = /(?<=_).*/.exec(prop)[0];
              let val =
                ctx.getValInParent(obj[k][prop], obj?.varys) ?? undefined; ///////////////////////在父实例中执行

              if (val === undefined) return; //
              newVarys[name] = val;
            } else {
              newVarys[prop] = obj[k][prop];
            }
          });
          obj[k] = newVarys;
        }
        if (k === "formItemProps") {
          if ("_prop" in obj[k]) {
            let val =
              ctx.getValInParent(obj[k]["_prop"], obj?.varys) ?? undefined;
            val && (ctx.formProp_conf[val] = obj[k]);
          }
          if (obj?.[k]?.prop) {
            ctx.formProp_conf[obj[k].prop] = obj[k];
          }
        }
        if (
          Object.prototype.toString.call(obj[k]) === "[object Object]" &&
          k !== "varys"
        ) {
          ctx.getFlatJson(obj[k], undefined, newObj);
        } else {
          if (evalKeys && k.startsWith("_")) {
            ////bind变量
            let name = /(?<=_).*/.exec(k)[0];
            let val = ctx.getValInParent(obj[k], obj?.varys) ?? undefined; ///////////////////////在父实例中执行

            if (val === undefined) return; /////????
            let prop = ctx.mergeProp.find((e) => {
              if (e === name) {
                return true;
              }
            });
            if (prop && newObj[prop] !== undefined) {
              newObj[prop] += " " + val;
              /////string格式 后面改
            } else newObj[name] = val ?? newObj[name];
          } else {
            newObj[k] = obj[k] ?? newObj[k];
          }
        }
      });

      return newObj;
    },
    getRowItem(e: Object, no, isCustom = false) {
      let ctx = this;

      let child;
      if (e.defautOptions) {
        //class对象???
        e = e.value;
      }
      //  if (e.components.length === 1 && e.components[0].customType) {
      ////自定义块/行元素
      //    child = ctx.getComs(e.components, undefined, isCustom)
      //  } else {
      e.varys &&
        e.components.forEach((ee) => {
          ee.varys = e.varys;
        });
      child = ctx.getCols(e.components, isCustom);
      // }
      let item;
      item = (
        <ElRow
          class={e.class}
          style={e.style}
          {...ctx.getFlatJson(e)} //e?.props ??
        >
          {child}
        </ElRow>
      );
      return item;
    },
    getRow(conf: Array<[Object]> | Object) {
      let ctx = this;

      let rowList: Array<[Object]> = [];
      conf.forEach((e: any) => {
        if (!e) return;
        let item = ctx.getRowItem(e);
        rowList.push(item);
      });
      return rowList;
    },
    getCols(conf: Array<[Object]>, isCustom = false) {
      let ctx = this;
      if (!conf) return [];
      let comList: Array<[Object]> = [];
      conf.forEach((e: any) => {
        if (e.defautOptions) {
          //class对象
          e = e.value;
        }
        let item;

        let res = deepClone(e);
        let orderList = ["v_if"]; //, "v_show"
        orderList.forEach((order) => {
          if ("_" + order in e) {
            let val =
              ctx.getValInParent(res["_" + order], res?.varys) ??
              ctx.form[res["_" + order]] ??
              undefined;
            res[order] = val;
            delete res["_" + order];
          }
        }); //change
        if (res["v_if"] !== undefined && ctx.useIf !== false) {
          if (!res["v_if"]) return null;
        }
        // if (res["v_show"] !== undefined) {
        //   res["style"] = res["style"]
        //     ? " display:none; !important"
        //     : (res["style"] += " display:none; !important");
        // }
        item = (
          <ElCol span={e.span} push={e.push} offset={e.offset}>
            {[ctx.getComs(e, undefined, isCustom)]}
          </ElCol>
        );
        comList.push(item);
      });
      return comList;
    },
    getComs(conf: any, isflat = false, isCustom = false) {
      let ctx = this;

      let flatConf = isflat ? conf : ctx.getFlatJson(conf, false); ////可能含v-for 先不eval
      flatConf = isflat ? flatConf : ctx.handleVueOrder(flatConf);
      if (!flatConf) return; //v_if
      flatConf = isflat ? flatConf : ctx.bindEvents(flatConf);
      // if (isCustom && !flatConf.belongParent) {
      //   //块级子元素添加父组件标识
      //   ////配置未更新
      //   flatConf.belongParent = isCustom
      // }
      if (flatConf?.customType) {
        isCustom = flatConf?.customType ? flatConf.selfIndex : null;
      }
      Object.keys(flatConf)?.forEach((k) => {
        ///执行eval 动态绑定
        if (k.startsWith("_")) {
          ////bind变量
          let name = /(?<=_).*/.exec(k)[0];
          let val;
          if (typeof flatConf[k] == "function") val = flatConf[k];
          else
            val =
              ctx.getValInParent(flatConf[k], flatConf?.varys) ??
              ctx.form[flatConf[k]] ??
              undefined;
          if (val === undefined) return;
          let prop = ctx.mergeProp.find((e) => {
            if (e === name) {
              return true;
            }
          });
          if (prop && flatConf[prop] !== undefined) {
            flatConf[prop] += " " + val;
            /////string格式 后面改
          } else flatConf[name] = val ?? flatConf[name];
        }
      });
      if (!flatConf) return;
      if (Array.isArray(flatConf)) {
        return flatConf.map((e) => {
          /////varys???
          return ctx.getComs(e, true);
        });
      }
      let renderCom;
      // let com = (conf.comName?.toLowerCase().startsWith("el")
      //   ? markRaw(this.customCom[conf.comName])
      //   : conf.comName)
      let comName = ctx.toCamelCase(flatConf.comName.trim());

      const com = this.customCom[comName] ?? comName;
      if (flatConf["v_model"] !== undefined) {
        if (Array.isArray(flatConf["v_model"])) {
          //[prop1][prop11]
          flatConf["v_model"].forEach((e, i) => {
            if (
              typeof e == "string" &&
              e.includes("varys.") &&
              flatConf.varys
            ) {
              //替换变量
              flatConf["v_model"][i] = eval(
                e.replaceAll("varys.", "flatConf.varys.")
              );
            }
          });
        } else {
          let str = null;
          if (flatConf["v_model"]?.startsWith("form.")) {
            str = /\.([^.]*)/.exec(flatConf["v_model"])[1];
          }
          if (flatConf["v_model"]?.startsWith("form[")) {
            str = /\[(.*?)\]/.exec(flatConf["v_model"])[1];
          }
          flatConf["v_model"] = str ?? flatConf["v_model"];
          //加工格式form.x ||form['x']
        }
      }
      let bindProp = (ctx.isBind === false ? null : flatConf["v_model"])
        ? Array.isArray(flatConf["v_model"])
          ? flatConf["v_model"]
          : ctx.form[flatConf["v_model"]] ?? undefined
        : null;

      const getChild = (arr, method, isCustom = false, varys) => {
        let childObj = {};
        let res = [];
        let hasSlot = false;
        arr.forEach((e: any) => {
          if (e.slotName) {
            hasSlot = true;
          }
          varys && (e.varys = varys);
          let name = e.slotName ?? "default";
          // if (e.slotName) {
          let r = ctx[method](e, undefined, isCustom);
          if (!childObj[name]) childObj[name] = [];
          childObj[name].push(e);
          res.push(r);
        });
        Object.keys(childObj).forEach((k) => {
          let arr = childObj[k];
          if (arr.length) {
            let val = childObj[k].map((e) =>
              ctx[method](e, undefined, isCustom)
            );
            childObj[k] = () => <Fragment>{val}</Fragment>; //{getChildObj(childObj[k])}
          }
        });
        return hasSlot ? childObj : res;
        // return [res, childObj]
      };
      let child = flatConf.childNode?.length
        ? getChild(flatConf.childNode, "getComs", isCustom, flatConf.varys)
        : flatConf.innerText ?? flatConf.contentText;
      if (isCustom && flatConf.template?.length) {
        child = flatConf.template?.length
          ? getChild(flatConf.template, "getRowItem", isCustom, flatConf.varys)
          : flatConf.innerText ?? flatConf.contentText;

        //|| ctx.getRow(flatConf.template)
      }

      // if (flatConf.comName.includes('ollapse')) {
      //   // let a = <div >test11111</div>, b = <div >tes2222</div>
      //   // child = { body: () => <Fragment >{a, b}</Fragment > }
      // }
      //child = (typeof child === 'Object') ? ({ ...child }) : (child)
      //?change
      if (bindProp === null) renderCom = <com {...flatConf}>{child}</com>;
      else if (!Array.isArray(bindProp)) {
        renderCom = (
          <com {...flatConf} v-model={ctx.form[flatConf["v_model"]]}>
            {child}
          </com>
        );
      } else {
        try {
          if (bindProp.length === 1)
            renderCom = (
              <com {...flatConf} v-model={ctx.form[flatConf["v_model"][0]]}>
                {child}
              </com>
            );
          if (bindProp.length === 2)
            renderCom = (
              <com
                {...flatConf}
                v-model={
                  ctx.form[flatConf["v_model"][0]][flatConf["v_model"][1]]
                }
              >
                {child}
              </com>
            );
          if (bindProp.length === 3)
            renderCom = (
              <com
                {...flatConf}
                v-model={
                  ctx.form[flatConf["v_model"][0]][flatConf["v_model"][1]][
                  flatConf["v_model"][2]
                  ]
                }
              >
                {child}
              </com>
            );
          if (bindProp.length === 4)
            renderCom = (
              <com
                {...flatConf}
                v-model={
                  ctx.form[flatConf["v_model"][0]][flatConf["v_model"][1]][
                  flatConf["v_model"][2]
                  ][flatConf["v_model"][3]]
                }
              >
                {child}
              </com>
            );
          if (bindProp.length === 5)
            renderCom = (
              <com
                {...flatConf}
                v-model={
                  ctx.form[flatConf["v_model"][0]][flatConf["v_model"][1]][
                  flatConf["v_model"][2]
                  ][flatConf["v_model"][3]][flatConf["v_model"][4]]
                }
              >
                {child}
              </com>
            );
        } catch (error) {
          debugger;
        }
      }

      if (flatConf["v_html"]) {
        renderCom = (
          <com {...flatConf} v-html={flatConf["v_html"]}>
            {child}
          </com>
        );
      }

      let extendProp = {};
      let flgDom = (e) => {
        return e?.attributes?.eventObj?.value;
      };

      if (ctx.dragEvent?.length) {
        extendProp = {
          onMouseover: (e) => {
            let item = getTargetDom(e.target, flgDom);

            ctx.currentCom = item;
            e.stopPropagation();
          },
          onMouseleave: (e) => {
            ctx.currentCom = null;
            let item = getTargetDom(e.target, flgDom);
            e.stopPropagation();
          },
          eventObj: conf.selfIndex ?? null,
          class: "isComContainer",
        };
      }
      if (ctx.clickEvent) {
        extendProp = {
          ...extendProp,
          eventObj: flatConf.selfIndex ?? null,
          onClick: (e) => {
            let dom = getTargetDom(e.target, flgDom);

            ctx.$emit(ctx.clickEvent, flatConf, dom);
            e.stopPropagation();
          },
          style: "height:fit-content",
          class: "isComContainer",
        };
      }
      if (conf.formItemProps?.prop || conf.formItemProps?.label) {
        let formItemCom;
        let reqclass =
          conf.formItemProps?.isRequired || conf.formItemProps?.required
            ? "is-required"
            : "";
        //class={conf.formItemProps?.isRequired ? "is-required" : ''}
        formItemCom = (
          <ElFormItem {...ctx.getFlatJson(conf.formItemProps)} class={reqclass}>
            {renderCom}
          </ElFormItem>
        );
        if (!extendProp.class) return formItemCom;
        return <div {...extendProp}>{formItemCom}</div>;
      } else {
        if (!extendProp.class) return renderCom;
        return <div {...extendProp}>{renderCom}</div>;
      }
    },
    handleVueOrder(conf: any) {
      let ctx = this;
      let orderList = ["v_if", "v_show", "v_for"];
      let res = deepClone(conf);
      if ("_" + "v_for" in conf) {
        //暂不处理v_if等指令 可能用到v_for变量
        orderList = ["v_for"];
      }
      orderList.forEach((order) => {
        if ("_" + order in conf) {
          let val =
            ctx.getValInParent(res["_" + order], res?.varys) ??
            ctx.form[res["_" + order]] ??
            undefined;
          res[order] = val;
          delete res["_" + order];
        }
      }); //change

      if (
        res["v_for"] !== undefined &&
        Array.isArray(res["v_for"]) &&
        res["v_for"].length
      ) {
        let list = res["v_for"][0];
        if (typeof list === "string")
          list = ctx.getValInParent(list, res?.varys) ?? [];
        let item = res["v_for"][1] ?? "item";
        let index = res["v_for"][2] ?? "i";
        if (Array.isArray(list)) {
          res = list.map((e, i) => {
            let newConf = deepClone(res); // JSON.parse(JSON.stringify(conf))
            if (!newConf["varys"]) newConf["varys"] = {};
            newConf["varys"][item] = e;
            newConf["varys"][index] = i;

            orderList = ["v_if", "v_show"];
            //处理v_if等指令
            orderList.forEach((order) => {
              if ("_" + order in newConf) {
                let val =
                  ctx.getValInParent(newConf["_" + order], newConf?.varys) ??
                  ctx.form[newConf["_" + order]] ??
                  undefined;
                newConf[order] = val;
                delete newConf["_" + order];
              }
            });
            if ("v_if" in newConf) {
              if (!newConf["v_if"] && ctx.useIf !== false) return null;
            }
            if ("v_show" in newConf && !newConf["v_show"]) {
              newConf["style"] = newConf["style"]
                ? (newConf["style"] += " display:none; !important")
                : " display:none; !important";
            }
            delete newConf["v_for"];
            return newConf;
          });
          return res;
        } else if (typeof list === "object" && list !== null) {
          let newRes = [];
          Object.keys(list).forEach((k) => {
            let newConf = deepClone(res); // JSON.parse(JSON.stringify(conf))
            if (!newConf["varys"]) newConf["varys"] = {};
            newConf["varys"][item] = list[k];
            newConf["varys"][index] = k;
            delete newConf["v_for"];
            newRes.push(newConf);
          });
          return newRes;
        }
      }
      if ("v_if" in res) {
        if (!res["v_if"] && ctx.useIf !== false) return null;
      }
      if ("v_show" in res && !res["v_show"]) {
        res["style"] = res["style"]
          ? (res["style"] += " display:none; !important")
          : " display:none; !important";
      }
      return res;
    },
  },
  render(ctx) {
    ctx.formProp_conf = markRaw({});
    // ctx.form = new Proxy({}, {
    //   get: (target, prop, c) => {
    //     return ctx.formConf?.props?.model?.[prop];
    //   },
    //   set: (target, prop, value) => {
    //     try {
    //       ctx.formConf?.props?.model[prop] = value;
    //       return true;
    //     } catch (error) {
    //       console.log(error);
    //       return false;
    //     }
    //   },
    // });
    // ctx.form = ctx.formConf?.props?.model ?? {};
    //ctx.form = markRaw(ctx.formConf?.props?.model ?? {});
    if (!ctx.formConf || (!ctx.visible && ctx.visible !== undefined))
      return <div></div>;
    // if (ctx.slotName) {
    //   return (<div>{ctx.getRow(ctx.formConf.template)}</div>)
    //   return {
    //     [ctx.slotName]: () => <div>{ctx.getRow(ctx.formConf.template)}</div>
    //   }
    // }
    this.form = this.formConf?.props?.model;
    if (ctx.dragEvent) {
      return (
        <ElForm
          v-draggable
          {...ctx.getFlatJson(ctx.formConf)}
          model={ctx.form}
          ref={ctx.formName}
          validate-on-rule-change
        >
          {ctx.getRow(ctx.formConf.template)}
        </ElForm>
      );
    }
    ctx.$nextTick(() => {
      ctx.updateRule();
    });
    return (
      <ElForm
        {...ctx.getFlatJson(ctx.formConf)}
        rules={ctx.rules}
        model={ctx.form}
        ref={ctx.formName}
      >
        {ctx.getRow(ctx.formConf.template)}
      </ElForm>
    );
  },
  mounted() {
    let ctx = this;
    if (!ctx.formConf) return;
    ctx.formConf.formRef = () => ctx.$refs[ctx.formName];
    // ctx.form = new Proxy(
    //   {},
    //   {
    //     get: () => ctx.formConf?.props?.model,
    //     set: (a, b, c) => {
    //       ctx.formConf.props.model[b] = c;
    //       return true;
    //     },
    //   }
    // );
    ctx.updateRule(true, "immediate");
  },
  directives: {
    draggable: {
      mounted: function (el, binding, vnode) {
        let ctx = binding.instance;
        el.style.cursor = "grab";
        const parent = el;
        //parent.style['overflow-y']
        const getUnitDom = (e, loop = 0) => {
          return ctx.currentCom;
        };
        const getRowByDom = (dom) => {
          let flg = (e) => {
            if (!e?.className) return false;
            // return e?.attributes?.selfIndex?.value?.includes("row_")
            return e?.className?.includes("el-row");
          };
          let rowDom = getTargetDom(dom, flg);
          return rowDom;
        };

        el.onmousedown = (e) => {
          if (!ctx.dragEvent?.length) return;
          el.style.cursor = "grabbing";
          let el1 = getUnitDom(e.target);
          if (!el1) return;
          let unDragItem = ctx.unDragList.find((e) => {
            if (
              el1.attributes.eventobj.value.split("_")[0].toLowerCase() ===
              e.toLowerCase()
            ) {
              return true;
            }
          });
          if (unDragItem) return;
          ctx.$emit(ctx.dragEvent[0]);
          ctx.isMoving = true;
          el1.className += " isMoving";
          let { clientX: ox, clientY: oy } = e;
          // let beforeIndex = el1?.attributes?.listIndex?.value;
          // if (!beforeIndex) return;
          let curDom = null;
          let curRow = null;
          let oIndex = el1.style.zIndex;
          el1.style.zIndex = "99";
          el1.style.pointerEvents = "none";
          el1.style.opacity = 0.75;
          document.onmousemove = function (e) {
            let { clientX: tx, clientY: ty } = e;
            el1.style.transform =
              "translate(" + (tx - ox) + "px," + (ty - oy) + "px)";
            // ctx.$nextTick(() => {
            let { x: cx, y: cy } = el1.getBoundingClientRect();
            curDom = document.elementFromPoint(cx, cy);
            if (curRow?.className) {
              curRow.className = curRow.className.replaceAll("isHover", "");
              curRow = null;
            }
            curRow = getRowByDom(curDom);
            if (curRow) {
              if (!curRow.className) curRow.className = "";
              curRow.className += " isHover";
            }
            // })
          };
          document.onmouseup = function (e) {
            el1.style.zIndex = oIndex;
            let { x: cx, y: cy } = el1.getBoundingClientRect();

            el1.style.transform = "unset";
            el1.style.opacity = "unset";
            el.style.cursor = "grab";
            el1.style.pointerEvents = "";

            document.onmouseup = document.onmousemove = null;
            ctx.isMoving = false;
            el1.className = el1.className.replaceAll("isMoving", "");
            // setTimeout(function () {
            let index = el1?.attributes?.eventObj?.value;
            if (!index) return;
            if (!curDom) return;
            curDom = document.elementFromPoint(cx, cy);

            if (curRow?.className) {
              curRow.className = curRow.className.replaceAll("isHover", "");
            }
            curRow = null;
            ctx.$emit(ctx.dragEvent[1], index, curDom, true, [cx, cy]);
            // index = index.split('_')[0]
            // }, 100);
          };
        };
      },
      unmounted(el, binding, vnode) {
        el.onmousedown = null;
      },
    },
  },
});
